﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;

namespace ExFlash.Tags
{
    public class DefineFontInfoTag : Tag, IReferenceCharacterId
    {
        protected readonly IDictionaryIdQueryable QuerySource;

        public ushort FontID
        {
            get;
            protected set;
        }

        [Browsable(false)]
        public Byte FontNameLen
        {
            get;
            protected set;
        }

        public Byte[] FontName
        {
            get;
            protected set;
        }

        public Boolean FontFlagsSmallText
        {
            get;
            protected set;
        }

        public Boolean FontFlagsShiftJIS
        {
            get;
            protected set;
        }

        public Boolean FontFlagsANSI
        {
            get;
            protected set;
        }

        public Boolean FontFlagsItalic
        {
            get;
            protected set;
        }

        public Boolean FontFlagsBold
        {
            get;
            protected set;
        }

        public Boolean FontFlagsWideCodes
        {
            get;
            protected set;
        }

        public ushort[] CodeTable
        {
            get;
            protected set;
        }

        public DefineFontInfoTag(int len, int offset, IDictionaryIdQueryable querySource)
            : this(TagCodes.DefineFontInfo, len, offset, querySource)
        {

        }

        protected DefineFontInfoTag(TagCodes code, int len, int offset, IDictionaryIdQueryable querySource)
            : base(code, len, offset)
        {
            QuerySource = querySource;
        }

        public override void SwfDeserialize(BinaryBitReader reader)
        {
            FontID = reader.ReadUInt16();

            FontNameLen = reader.ReadByte();

            FontName = new Byte[FontNameLen];
            reader.Read(FontName, 0, FontNameLen);

            // Reserved
            reader.SkipBits(2);

            FontFlagsSmallText = reader.ReadBoolean();
            FontFlagsShiftJIS = reader.ReadBoolean();
            FontFlagsANSI = reader.ReadBoolean();
            FontFlagsItalic = reader.ReadBoolean();
            FontFlagsBold = reader.ReadBoolean();
            FontFlagsWideCodes = reader.ReadBoolean();

            reader.AlignBits();

            Tag tag;
            DefineFontTag fontTag;

            if (QuerySource.TryGetValue(FontID, out tag) == false)
            {
                throw new SerializationException("DefineFontInfo Tag referring to unknown Font ID");
            }
            
            if ((fontTag = tag as DefineFontTag) == null)
            {
                throw new SerializationException("ID exists but doesn't belong to a font Tag");
            }

            CodeTable = new ushort[fontTag.NumGylphs];

            if (FontFlagsWideCodes)
            {
                for (int i = 0; i < fontTag.NumGylphs; i++)
                {
                    CodeTable[i] = reader.ReadUInt16();
                }
            }
            else
            {
                for (int i = 0; i < fontTag.NumGylphs; i++)
                {
                    CodeTable[i] = reader.ReadByte();
                }
            }
        }

        public override void SwfSerialize(byte[] arr, ref int offset)
        {
            throw new NotImplementedException();
        }

        public bool IsReferencing
        {
            get { return true; }
        }

        public ushort ReferencedId
        {
            get { return FontID; }
        }

        public IEnumerable<Type> ReferencedAttributes
        {
            get { return new List<Type> {typeof(FontTagAttribute)}; }
        }
    }
}
